package com.hellobike.haxing.modules.wms.facade.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hellobike.haxing.modules.product.entity.Sku;
import com.hellobike.haxing.modules.product.entity.Spu;
import com.hellobike.haxing.modules.product.service.ISkuService;
import com.hellobike.haxing.modules.product.service.ISpuService;
import com.hellobike.haxing.modules.shop.entity.Shop;
import com.hellobike.haxing.modules.shop.service.IShopService;
import com.hellobike.haxing.modules.supplier.entity.TSupplier;
import com.hellobike.haxing.modules.supplier.entity.TSupplierClPro;
import com.hellobike.haxing.modules.supplier.entity.TSupplierInfo;
import com.hellobike.haxing.modules.supplier.service.ITSupplierClProService;
import com.hellobike.haxing.modules.supplier.service.ITSupplierInfoService;
import com.hellobike.haxing.modules.wms.dto.ReturnSupplierDetailDto;
import com.hellobike.haxing.modules.wms.dto.ReturnSupplierHeaderDto;
import com.hellobike.haxing.modules.wms.dto.ReturnWarehouseDetailDto;
import com.hellobike.haxing.modules.wms.dto.ReturnWarehouseHeaderDto;
import com.hellobike.haxing.modules.wms.entity.*;
import com.hellobike.haxing.modules.wms.enums.*;
import com.hellobike.haxing.modules.wms.exception.WmsServiceException;
import com.hellobike.haxing.modules.wms.facade.WmsReceiveFacade;
import com.hellobike.haxing.modules.wms.facade.WmsReturnFacade;
import com.hellobike.haxing.modules.wms.service.*;
import com.hellobike.haxing.modules.wms.utils.ListUtil;
import com.hellobike.haxing.modules.wms.utils.WmsCodeGeneratorUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Component("wmsReturnFacade")
public class WmsReturnFacadeImpl implements WmsReturnFacade {

    @Autowired
    private IReturnSupplierDetailService returnSupplierDetailService;
    @Autowired
    private IReturnSupplierHeaderService returnSupplierHeaderService;
    @Autowired
    private IReturnWarehouseDetailService returnWarehouseDetailService;
    @Autowired
    private IReturnWarehouseHeaderService returnWarehouseHeaderService;
    @Autowired
    private IShippingHeaderService shippingHeaderService;
    @Autowired
    private IShippingDetailService shippingDetailService;
    @Autowired
    private IContainerService containerService;
    @Autowired
    private ISkuService skuService;
    @Autowired
    private ISpuService spuService;
    @Autowired
    private IShopService shopService;
    @Autowired
    private WmsReceiveFacade wmsReceiveFacade;
    @Autowired
    private ITSupplierClProService supplierClProService;
    @Autowired
    private ITSupplierInfoService supplierInfoService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void publishReturnWarehouseOrder(List<Long> detailIds, Long warehouseId, Integer userId) throws WmsServiceException {
        if (ListUtil.isNullOrEmpty(detailIds)) {
            throw new WmsServiceException("退货明细参数缺失");
        }

        Map<Long, List<ReturnWarehouseDetail>> shopReturnMap = new HashMap<>();
        for (Long detailId : detailIds) {
            ReturnWarehouseDetail returnWarehouseDetail = returnWarehouseDetailService.getById(detailId);
            if (returnWarehouseDetail == null) {
                throw new WmsServiceException("退货明细不存在" + detailId);
            }
            if (!returnWarehouseDetail.getWarehouseId().equals(warehouseId)) {
                throw new WmsServiceException("该退货不是当前仓库" + warehouseId);
            }
            if (!ReturnStatusEnum.INIT.getValue().equals(returnWarehouseDetail.getReturnStatus())) {
                throw new WmsServiceException("该退货明细状态不是初始化" + detailId);
            }
            shopReturnMap.computeIfAbsent(returnWarehouseDetail.getShopId(), k -> new ArrayList<>());
            shopReturnMap.get(returnWarehouseDetail.getShopId()).add(returnWarehouseDetail);
        }
        for (Map.Entry<Long, List<ReturnWarehouseDetail>> entry : shopReturnMap.entrySet()) {
            Long shopId = entry.getKey();
            List<ReturnWarehouseDetail> detailList = entry.getValue();
            ReturnWarehouseHeader header = new ReturnWarehouseHeader();
            header.setReturnType(ReturnWarehouseTypeEnum.ZTD.getValue());
            header.setReturnStatus(ReturnStatusEnum.WAIT_RETURN.getValue());
            header.setReturnCode(WmsCodeGeneratorUtil.createReturnWarehouseCode(warehouseId));
            header.setWarehouseId(warehouseId);
            header.setShopId(shopId);
            long boxCount = 0L, skuCount = 0L;
            for (ReturnWarehouseDetail returnWarehouseDetail : detailList) {
                if (ReturnTypeEnum.CONTAINER.getValue().equals(returnWarehouseDetail.getReturnType())) {
                    boxCount++;
                } else if (ReturnTypeEnum.SKU.getValue().equals(returnWarehouseDetail.getReturnType())) {
                    skuCount += returnWarehouseDetail.getReturnQty();
                }
            }
            header.setBoxCount(boxCount);
            header.setSkuCount(skuCount);
            returnWarehouseHeaderService.save(header);
            for (ReturnWarehouseDetail detail : detailList) {
                detail.setReturnHeaderId(header.getId());
                detail.setReturnHeaderCode(header.getReturnCode());
                detail.setReturnStatus(ReturnStatusEnum.WAIT_RETURN.getValue());
                returnWarehouseDetailService.updateById(detail);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void receiveReturnWarehouseOrder(Long headerId, List<ReturnWarehouseDetail> details, Long warehouseId, Integer userId) throws WmsServiceException {
        if (headerId == null) {
            throw new WmsServiceException("参数缺失");
        }
        if (ListUtil.isNullOrEmpty(details)) {
            throw new WmsServiceException("明细缺失");
        }
        ReturnWarehouseHeader returnWarehouseHeader = returnWarehouseHeaderService.getById(headerId);
        if (returnWarehouseHeader == null) {
            throw new RuntimeException("退货订单未找到");
        }
        ShippingDetail shippingDetail = shippingDetailService.getByDeliveryOrderIdAndType(headerId, ShippingTypeEnum.TH);
        if (shippingDetail == null) {
            throw new RuntimeException("订单发运信息未找到");
        }
        ShippingHeader shippingHeader = shippingHeaderService.getById(shippingDetail.getShippingHeaderId());
        if (shippingHeader == null) {
            throw new RuntimeException("订单发运信息未找到");
        }

        Map<Long, ReturnWarehouseDetail> detailMap = details.stream().collect(Collectors.toMap(ReturnWarehouseDetail::getId, d -> d));
        List<ReturnWarehouseDetail> returnWarehouseDetails = returnWarehouseDetailService.getByHeaderId(headerId);
        if (ListUtil.isNullOrEmpty(returnWarehouseDetails)) {
            throw new WmsServiceException("退货单明细缺失");
        }
        List<AsnDetail> asnDetails = new ArrayList<>();
        for (ReturnWarehouseDetail detail : returnWarehouseDetails) {
            ReturnWarehouseDetail param = detailMap.get(detail.getId());
            if (param == null) {
                throw new WmsServiceException("退货明细缺失" + detail.getId());
            }
            String returnStatus = param.getReturnStatus();
            String returnType = detail.getReturnType();
            if (ReturnTypeEnum.CONTAINER.getValue().equals(returnType)) {
                if (param.getReceivedQty() == 1) {
                    Container container = containerService.getById(detail.getBoxId());
                    if (container == null) {
                        throw new WmsServiceException("容器未找到");
                    }
                    container.setContainerStatus(ContainerStatusEnum.FREE.getValue());
                    container.setCurDocId(null);
                    container.setCurShopId(null);
                    containerService.updateById(container);
                }
            } else if (ReturnTypeEnum.SKU.getValue().equals(returnType)) {
                Integer receivedQty = param.getReceivedQty();
                if (receivedQty > detail.getReturnQty()) {
                    throw new WmsServiceException("收货数量不能大于退货数量");
                }
                if (receivedQty < 0) {
                    throw new WmsServiceException("收货数量不能小于0");
                }
                if (ReturnStatusEnum.RETURN_WAREHOUSE.getValue().equals(returnStatus)) {
                    if (receivedQty > 0) {
                        AsnDetail asnDetail = new AsnDetail();
                        asnDetail.setSkuId(detail.getSkuId());
                        asnDetail.setPurchaseCount(BigDecimal.valueOf(receivedQty));
                        asnDetail.setWarehouseId(warehouseId);
                        asnDetail.setSupplierId(-1L);
                        Sku sku = skuService.getById(detail.getSkuId());
                        if (sku != null) {
                            asnDetail.setPrice(sku.getPrice());
                        }
                        asnDetails.add(asnDetail);
                    }
                } else if (ReturnStatusEnum.RETURN_SUPPLIER.getValue().equals(returnStatus)) {
                    if (receivedQty > 0) {
                        ReturnSupplierDetail returnSupplierDetail = new ReturnSupplierDetail();
                        returnSupplierDetail.setSkuId(detail.getSkuId());
                        returnSupplierDetail.setSkuCode(detail.getSkuCode());
                        returnSupplierDetail.setBarcode(detail.getBarcode());
                        returnSupplierDetail.setProductId(detail.getProductId());
                        returnSupplierDetail.setRefOrderId(detail.getRefOrderId());
                        returnSupplierDetail.setRefOrderCode(detail.getRefOrderCode());
                        returnSupplierDetail.setReturnQty(receivedQty);
                        returnSupplierDetail.setReturnReason(detail.getReturnReason());
                        returnSupplierDetail.setReturnTime(detail.getReturnTime());
                        returnSupplierDetail.setReturnType(ReturnTypeEnum.SKU.getValue());
                        returnSupplierDetail.setReturnStatus(ReturnStatusEnum.INIT.getValue());
                        returnSupplierDetail.setShopId(detail.getShopId());
                        returnSupplierDetail.setWarehouseId(detail.getWarehouseId());
                        returnSupplierDetail.setSupplierId(getDefSupplierBySku(detail.getSkuId()));
                        returnSupplierDetail.setSkuStatus(SkuReturnStatusEnum.WH.getValue());
                        returnSupplierDetailService.save(returnSupplierDetail);
                    }
                }
            }
            detail.setReceivedQty(param.getReceivedQty());
            detail.setReceiveDiffReason(param.getReceiveDiffReason());
            detail.setReturnStatus(returnStatus);
            returnWarehouseDetailService.updateById(detail);
        }
        returnWarehouseHeader.setReturnStatus(ReturnStatusEnum.RETURN_SUCCESS.getValue());
        returnWarehouseHeaderService.updateById(returnWarehouseHeader);
        if (asnDetails.size() > 0) {
            AsnHeader asnHeader = new AsnHeader();
            asnHeader.setConcatName("退货入库");
            asnHeader.setCarNo(shippingHeader.getCarNumber());
            asnHeader.setExptArriveTime(new Date());
            asnHeader.setRefOrderId(returnWarehouseHeader.getId());
            asnHeader.setRefOrderCode(returnWarehouseHeader.getReturnCode());
            asnHeader.setSupplierId(-1L);
            asnHeader.setWarehouseId(warehouseId);
            wmsReceiveFacade.addAsnByReturnExchange(asnHeader, asnDetails, warehouseId, userId);
        }
        List<ShippingDetail> shippingDetails = shippingDetailService.getByHeaderId(shippingHeader.getId());
        boolean isAllReceived = true;
        for (ShippingDetail detail : shippingDetails) {
            ReturnWarehouseHeader warehouseHeader = returnWarehouseHeaderService.getById(detail.getDeliveryHeaderId());
            if (warehouseHeader == null) {
                throw new RuntimeException("订单不存在");
            }
            if (!ReturnStatusEnum.RETURN_SUCCESS.getValue().equals(warehouseHeader.getReturnStatus())) {
                isAllReceived = false;
                break;
            }
        }
        if (isAllReceived) {//全部收货完成回写发运单
            shippingHeader.setShippingStatus(ShippingStatusEnum.COMPLETED.getValue());
            Long totalSkuQty = 0L;
            Long totalBoxQty = 0L;
            for (ShippingDetail detail : shippingDetails) {
                List<ReturnWarehouseDetail> detailList = returnWarehouseDetailService.getByHeaderId(detail.getDeliveryHeaderId());
                for (ReturnWarehouseDetail warehouseDetail : detailList) {
                    String returnStatus = warehouseDetail.getReturnStatus();
                    String returnType = warehouseDetail.getReturnType();
                    if (ReturnTypeEnum.CONTAINER.getValue().equals(returnType)) {
                        if (ReturnStatusEnum.RETURN_WAREHOUSE.getValue().equals(returnStatus)) {
                            totalBoxQty++;
                        }
                    } else if (ReturnTypeEnum.SKU.getValue().equals(returnType)) {
                        if (ReturnStatusEnum.RETURN_WAREHOUSE.getValue().equals(returnStatus) ||
                                ReturnStatusEnum.RETURN_SUPPLIER.getValue().equals(returnStatus)) {
                            totalSkuQty += warehouseDetail.getReceivedQty();
                        }
                    }
                }

            }
            shippingHeader.setReceiveBoxCount(totalBoxQty);
            shippingHeader.setReceiveCount(totalSkuQty);
            shippingHeaderService.updateById(shippingHeader);
        }

    }

    private Long getDefSupplierBySku(Long skuId) {
        TSupplierClPro param = new TSupplierClPro();
        param.setSkuId(skuId);
        Wrapper<TSupplierClPro> wrapper = new QueryWrapper<>(param);
        List<TSupplierClPro> tSupplierClPros = supplierClProService.getBaseMapper().selectList(wrapper);
        if(ListUtil.isNotEmpty(tSupplierClPros)){
            for (TSupplierClPro tSupplierClPro : tSupplierClPros) {
                if(null != tSupplierClPro.getIsDefault() && tSupplierClPro.getIsDefault() == 1){
                    return tSupplierClPro.getSupplierId();
                }
            }
            return tSupplierClPros.get(0).getSupplierId();
        }
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addReturnSupplierOrder(ReturnSupplierHeader supplierHeader, List<Long> detailIds, Long warehouseId, Integer userId) throws WmsServiceException {
        if (supplierHeader == null || ListUtil.isNullOrEmpty(detailIds)) {
            throw new WmsServiceException("参数缺失");
        }
        supplierHeader.setWarehouseId(warehouseId);
        supplierHeader.setReturnType(ReturnSupplierTypeEnum.WH.getValue());
        supplierHeader.setReturnStatus(ReturnStatusEnum.WAIT_RETURN.getValue());
        supplierHeader.setReturnCode(WmsCodeGeneratorUtil.createReturnSupplierCode(warehouseId));
        returnSupplierHeaderService.save(supplierHeader);
        List<ReturnSupplierDetail> details = new ArrayList<>();
        long skuCount = 0L;
        for (Long detailId : detailIds) {
            ReturnSupplierDetail supplierDetail = returnSupplierDetailService.getById(detailId);
            if (supplierDetail == null) {
                throw new WmsServiceException("商品不存在");
            }
            if(!ReturnStatusEnum.INIT.getValue().equals(supplierDetail.getReturnStatus())){
               throw new WmsServiceException("退货商品状态异常");
            }
            supplierDetail.setReturnHeaderId(supplierHeader.getId());
            supplierDetail.setReturnHeaderCode(supplierHeader.getReturnCode());
            supplierDetail.setReturnStatus(ReturnStatusEnum.WAIT_RETURN.getValue());
            supplierDetail.setSupplierId(supplierHeader.getSupplierId());
            skuCount +=supplierDetail.getReturnQty();
            returnSupplierDetailService.updateById(supplierDetail);
        }
        if(skuCount != supplierHeader.getSkuCount()){
            supplierHeader.setSkuCount(skuCount);
            returnSupplierHeaderService.updateById(supplierHeader);
        }


    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void confirmReturnSupplierOrder(Long headerId, List<ReturnSupplierDetail> details, Long warehouseId, Integer userId) throws WmsServiceException {

    }

    @Override
    public IPage<ReturnWarehouseDetailDto> wrapperPageWarehouseDetail(IPage<ReturnWarehouseDetail> pageList) {
        IPage<ReturnWarehouseDetailDto> result = new Page<>();
        result.setCurrent(pageList.getCurrent());
        result.setPages(pageList.getPages());
        result.setSize(pageList.getSize());
        result.setTotal(pageList.getTotal());
        List<ReturnWarehouseDetailDto> rs = new ArrayList<>();
        if (ListUtil.isNotEmpty(pageList.getRecords())) {
            for (ReturnWarehouseDetail record : pageList.getRecords()) {
                ReturnWarehouseDetailDto dto = new ReturnWarehouseDetailDto();
                BeanUtils.copyProperties(record,dto);
                if(ReturnTypeEnum.SKU.getValue().equals(record.getReturnType())){
                    Sku sku = skuService.getById(record.getSkuId());
                    if(null != sku){
                        Spu spu = spuService.getById(sku.getSpuId());
                        dto.setBarcode(sku.getBarcode());
                        dto.setSkuCode(sku.getSkuCode());
                        dto.setSpuCode(spu.getSpuCode());
                        dto.setSpuName(spu.getSpuName());
                        dto.setDimensionValues(sku.getDimensionValues());
                    }
                }
                Shop shop = shopService.getById(record.getShopId());
                dto.setShopName(shop.getShopName());
                rs.add(dto);
            }
        }
        result.setRecords(rs);
        return result;
    }

    @Override
    public IPage<ReturnWarehouseHeaderDto> wrapperPageWarehouseHeader(IPage<ReturnWarehouseHeader> pageList) {
        IPage<ReturnWarehouseHeaderDto> result = new Page<>();
        result.setCurrent(pageList.getCurrent());
        result.setPages(pageList.getPages());
        result.setSize(pageList.getSize());
        result.setTotal(pageList.getTotal());
        List<ReturnWarehouseHeaderDto> rs = new ArrayList<>();
        if (ListUtil.isNotEmpty(pageList.getRecords())) {
            for (ReturnWarehouseHeader record : pageList.getRecords()) {
                ReturnWarehouseHeaderDto dto = new ReturnWarehouseHeaderDto();
                BeanUtils.copyProperties(record,dto);
                Shop shop = shopService.getById(record.getShopId());
                dto.setShopName(shop.getShopName());
                rs.add(dto);
            }
        }
        result.setRecords(rs);
        return result;
    }

    @Override
    public List<ReturnWarehouseHeaderDto> queryListByShippingHeaderId(Long shippingHeaderId) {
        List<ReturnWarehouseHeaderDto> rs = new ArrayList<>();
        List<ShippingDetail> shippingDetails = shippingDetailService.getByHeaderId(shippingHeaderId);
        if(ListUtil.isNotEmpty(shippingDetails)){
            for (ShippingDetail shippingDetail : shippingDetails) {
                ReturnWarehouseHeader warehouseHeader = returnWarehouseHeaderService.getById(shippingDetail.getDeliveryHeaderId());
                ReturnWarehouseHeaderDto dto = new ReturnWarehouseHeaderDto();
                BeanUtils.copyProperties(warehouseHeader,dto);
                Shop shop = shopService.getById(warehouseHeader.getShopId());
                dto.setShopName(shop.getShopName());
                rs.add(dto);
            }
        }
        return rs;
    }

    @Override
    public IPage<ReturnSupplierDetailDto> wrapperPageSupplierDetail(IPage<ReturnSupplierDetail> pageList) {
        IPage<ReturnSupplierDetailDto> result = new Page<>();
        result.setCurrent(pageList.getCurrent());
        result.setPages(pageList.getPages());
        result.setSize(pageList.getSize());
        result.setTotal(pageList.getTotal());
        List<ReturnSupplierDetailDto> rs = new ArrayList<>();
        if (ListUtil.isNotEmpty(pageList.getRecords())) {
            for (ReturnSupplierDetail record : pageList.getRecords()) {
                ReturnSupplierDetailDto dto = new ReturnSupplierDetailDto();
                BeanUtils.copyProperties(record,dto);
                if(ReturnTypeEnum.SKU.getValue().equals(record.getReturnType())){
                    Sku sku = skuService.getById(record.getSkuId());
                    if(null != sku){
                        Spu spu = spuService.getById(sku.getSpuId());
                        dto.setBarcode(sku.getBarcode());
                        dto.setSkuCode(sku.getSkuCode());
                        dto.setSpuCode(spu.getSpuCode());
                        dto.setSpuName(spu.getSpuName());
                        dto.setDimensionValues(sku.getDimensionValues());
                    }
                }
                if(null != record.getSupplierId()){
                    TSupplierInfo supplier = supplierInfoService.getById(record.getSupplierId());
                    if (supplier != null) {
                        dto.setSupplierName(supplier.getSupplierName());
                    }
                }
                if(-1L == record.getShopId()){
                    dto.setShopName("无门店");
                }else {
                    Shop shop = shopService.getById(record.getShopId());
                    dto.setShopName(shop.getShopName());
                }

                rs.add(dto);
            }
        }
        result.setRecords(rs);
        return result;
    }

    @Override
    public IPage<ReturnSupplierHeaderDto> wrapperPageSupplierHeader(IPage<ReturnSupplierHeader> pageList) {
        IPage<ReturnSupplierHeaderDto> result = new Page<>();
        result.setCurrent(pageList.getCurrent());
        result.setPages(pageList.getPages());
        result.setSize(pageList.getSize());
        result.setTotal(pageList.getTotal());
        List<ReturnSupplierHeaderDto> rs = new ArrayList<>();
        if (ListUtil.isNotEmpty(pageList.getRecords())) {
            for (ReturnSupplierHeader record : pageList.getRecords()) {
                ReturnSupplierHeaderDto dto = new ReturnSupplierHeaderDto();
                BeanUtils.copyProperties(record,dto);
                TSupplierInfo supplier = supplierInfoService.getById(record.getSupplierId());
                if (supplier != null) {
                    dto.setSupplierName(supplier.getSupplierName());
                }
                rs.add(dto);
            }
        }
        result.setRecords(rs);
        return result;
    }
}
